#include "pthread.hpp"
#include <iostream>
#include <string>
#include <unistd.h>

std::string GetThreadName()
{
    static int num = 1;
    char buf[64];
    snprintf(buf, sizeof(buf), "thread - %d ", num++);
    return buf;
}

void Print(int num)
{
    while (num)
    {
        std::cout << num-- << std::endl;
        sleep(1);
    }
}

class TData
{
public:
    TData(std::string name, pthread_mutex_t *pmutex)
        : _name(name), _pmutex(pmutex)
    {
    }

    ~TData()
    {
    }

public:
    std::string _name;
    pthread_mutex_t *_pmutex;
};

static int tikets = 10000;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void GetTiket(void *args)
{
    TData *td = (TData *)args;
    while (true)
    {
        // 加锁
        pthread_mutex_lock(td->_pmutex);
        if (tikets > 0)
        {
            usleep(100);
            std::cout << td->_name.c_str() << "get a tiket: " << tikets << std::endl;
            tikets--;
            pthread_mutex_unlock(td->_pmutex);
        }
        else
        {
            pthread_mutex_unlock(td->_pmutex);
            break;
        }
    }
}

int main()
{
    // std::string name1 = GetThreadName();
    // Thread<std::string> t1(name1, GetTiket, name1);

    // std::string name2 = GetThreadName();
    // Thread<std::string> t2(name2, GetTiket, name2);

    // std::string name3 = GetThreadName();
    // Thread<std::string> t3(name3, GetTiket, name3);

    // std::string name4 = GetThreadName();
    // Thread<std::string> t4(name4, GetTiket, name4);

    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);

    // 创建线程
    std::string name1 = GetThreadName();
    TData *td1 = new TData(name1, &mutex);
    Thread<TData *> t1(name1, GetTiket, td1);

    std::string name2 = GetThreadName();
    TData *td2 = new TData(name2, &mutex);
    Thread<TData *> t2(name2, GetTiket, td2);

    std::string name3 = GetThreadName();
    TData *td3 = new TData(name3, &mutex);
    Thread<TData *> t3(name3, GetTiket, td3);

    std::string name4 = GetThreadName();
    TData *td4 = new TData(name4, &mutex);
    Thread<TData *> t4(name4, GetTiket, td4);

    t1.Start();
    t2.Start();
    t3.Start();
    t4.Start();
    t1.Join();
    t2.Join();
    t3.Join();
    t4.Join();

    return 0;
}